﻿// Parse name to get Gun Size : Implement them phan 1 11/16" x 6.0m HMX
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace DienLib.ReportLib
{
    public class EnumsStructs
    {
        #region ExplosiveType
        // Summary:
        //     Represents an Explosive Type
        [Serializable]
        public struct ExplosiveType
        {
            string _PartNumber;
            /// <summary>
            /// Get the PartNumber of ExplosiveType
            /// </summary>
            public string PartNumber
            {
                get { return _PartNumber; }
            }

            string _Name;
            /// <summary>
            /// Get the Name of ExplosiveType
            /// </summary>
            public string Name
            {
                get { return _Name; }
            }

            /// <summary>
            /// Represents an Explosive that is null.
            /// </summary>
            public static readonly ExplosiveType Empty;

            public static bool operator !=(ExplosiveType left, ExplosiveType right)
            {
                return !(left == right);
            }

            public static bool operator ==(ExplosiveType left, ExplosiveType right)
            {
                return (left._Name == right.Name) & (left.PartNumber == right.PartNumber);
            }

            public static ExplosiveType BoosterHMX
            {
                get { return new ExplosiveType("Bi Di Booster", "160251"); }
            }

            public static ExplosiveType BoosterHNS
            {
                get { return new ExplosiveType("HNS BOOSTERS - DW Z909", "100157004"); }
            }

            public static ExplosiveType Charge2MF
            {
                get { return new ExplosiveType("CHARGES 2\" MAX FORCE, HMX", "101603801"); }
            }

            public static ExplosiveType Charge2ML
            {
                get { return new ExplosiveType("CHARGES 2\" JRC Millennium HMX", "101208224"); }
            }

            public static ExplosiveType Charge2SW
            {
                get { return new ExplosiveType("CHARGES 2\" SIDEWINDER II, HNS, DP", "100157018"); }
            }

            public static ExplosiveType CordHMX
            {
                get { return new ExplosiveType("DET. CORD HMX 40 GR/FT RIBBON LS", "101205518"); }
            }

            public static ExplosiveType CordHNS
            {
                get { return new ExplosiveType("DET. CORD, HNS LEAD, 60 GR", "458688"); }
            }

            public static ExplosiveType DetRB
            {
                get { return new ExplosiveType("DETONATOR, RED BLOCK", "101272580"); }
            }

            public static ExplosiveType DetRT
            {
                get { return new ExplosiveType("DETONATOR, RED TOP FIRE", "101272595"); }
            }

            public static ExplosiveType DetEBW1
            {
                get { return new ExplosiveType("DETONATOR,CP,400F,EBW-PSCI-401", "454605"); }
            }

            public static ExplosiveType DetEBW2
            {
                get { return new ExplosiveType("DETONATOR,CP,400F,EBW-PSCI-401", "456322"); }
            }

            public static ExplosiveType IgnitorTR
            {
                get { return new ExplosiveType("IGNITOR, THERMAL RED", "101320910"); }
            }

            public static ExplosiveType IgnitorRES1
            {
                get { return new ExplosiveType("IGNITOR RESISTORIZED (DET-5306-074)", "100004220"); }
            }

            public static ExplosiveType IgnitorRES2
            {
                get { return new ExplosiveType("IGNITOR RESISTORIZED (DET-5306-074)", "100010588"); }
            }

            public static ExplosiveType Gun2JRC21FT
            {
                get { return new ExplosiveType("JRC 2\" (6.4m) 21ft, 6 SPF, 60 Deg", "101234529"); }
            }

            public static ExplosiveType Gun2JRC15FT
            {
                get { return new ExplosiveType("JRC 2\" (4.5m) 15ft, 6 SPF, 60 Deg", "101235975"); }
            }

            public static ExplosiveType Gun2JRC11FT
            {
                get { return new ExplosiveType("JRC 2\" (3.4m) 11ft, 6 SPF, 60 Deg", "101234526"); }
            }

            public static ExplosiveType Gun2JRC7FT
            {
                get { return new ExplosiveType("JRC 2\" (2.1m) 7ft, 6 SPF, 60 Deg", "101234525"); }
            }

            public static ExplosiveType Gun2JRC4FT
            {
                get { return new ExplosiveType("JRC 2\" (1.2m) 4ft, 6 SPF, 60 Deg", "101234455"); }
            }

            /// <summary>
            /// ExplosiveType Constructor
            /// </summary>
            /// <param name="name"></param>
            /// <param name="partno"></param>
            private ExplosiveType(string name, string partno)
            {
                _Name = name;
                _PartNumber = partno;
            }


            public override string ToString()
            {
                return this._Name;
            }
        }
        #endregion

        #region ServiceRun
        public struct ServiceRun
        {
            string _Name; // Done
            string _DeepestDepth; // Done
            double _MaxTemp; // Done
            string _Engineer; // Done
            string _Status; // Done

            DateTime _StartTime;
            DateTime _StopTime;

            DateTime _Date;
            uint _RunNo; // Done
            EnumsStructs.ServiceType _ServiceName;
            string _Description;
            double _PerfLogFrom;
            double _PerfLogTo;
            double _Quantity;
            string _Unit;
            double _UnitPrice;
            double _Amount;

            public EnumsStructs.KnownServiceType Type { get; private set; }

            public EnumsStructs.RunStatus Status { get; private set; }

            public double TopMD { get; private set; }

            public double BottomMD { get; private set; }

            /// <summary>
            /// Convert to PERFROW for use with SummitLib
            /// </summary>
            /// <param name="gunNo">Gun Number : Check ServiceRuns List by "Count if" Type is PERF & Success</param>
            /// <returns>PERFROW for Summit PerfLib.AddPerforation</returns>
            public SummitLib.PERFROW ToPERFROW(uint gunNo)
            {
                //public PERFROW(int gun, int run, int mTopShot, int mBotShot, Enums.GunSize gunSize, Enums.SPF sPF, Enums.Polarity polarity, string comment)
                return new SummitLib.PERFROW(gunNo, this._RunNo, this.TopMD, this.BottomMD, this.toGunSize(), SummitLib.Enums.SPF._6SPF, SummitLib.Enums.Polarity.POSITIVE, this._Status);
            }

            public SummitLib.SERVICEROW ToSERVICEROW()
            {
                return new SummitLib.SERVICEROW(ServiceType.ToData(this.Type), this._RunNo, this.TopMD, this.BottomMD, this._Status);
            }

            private static double[] toMD(string drawdepth)
            {
                MatchCollection matches = Regex.Matches(drawdepth, @"[0-9.,]+");
                if (matches.Count == 0) throw new InvalidOperationException(string.Format("\"{0}\" don't have any depth number", drawdepth));
                List<double> list = new List<double>();
                foreach (Match match in matches)
                {
                    try { list.Add(Convert.ToDouble(match.ToString())); }
                    catch (Exception ex) { throw new InvalidOperationException(string.Format("\"{0}\" isn't a double number", match.ToString()) + "\r\n" + ex.Message); }
                }
                return list.ToArray();
            }

            private SummitLib.Enums.GunSize toGunSize()
            {   // Parse name to get Gun Size : Implement them phan 1 11/16" x 6.0m HMX
                if (this._ServiceName.Type == KnownServiceType.PERF)
                {
                    string size = Regex.Match(this._Name, @"(^|\s)([0-9.,]+)""").Groups[2].ToString(); // Try this : (^|\s)(([0-9]{1})[.,]{1}[0-9]*|([0-9]))"
                    // (^|\s) : start line hoac space
                    // [0-9.,] : so double bat ky

                    // Should implement as Company Man or Engineer (Check with eGunsize._arr)
                    // Temp Implement :
                    if (size.Contains("2")) return SummitLib.Enums.GunSize._2IN;
                    else if (size.Contains("1.")) return SummitLib.Enums.GunSize._1IN11_16;


                    size = Regex.Match(this._Name, @"([0-9]{1})[^a-z0-9]+[0-9]+/[0-9]+""").Groups[1].ToString();
                    // [0-9]{1} : 1 so tu 0 den 9 gunsize phan nguyen
                    // [^a-z0-9]+ : bat ky khoang trang, +, -, *, / ..v.v.. lam dau noi phan so (khong phai ky tu hay so la duoc)
                    // [0-9]+/[0-9]+ : phan thap phan cua phan so eg : 3/4 hoac 11/16
                    if (size.Contains('2')) return SummitLib.Enums.GunSize._2IN; // Should be 2 3/4"
                    else if (size.Contains('1')) return SummitLib.Enums.GunSize._1IN11_16; // Should implement check group 2 also

                    return SummitLib.Enums.GunSize.NA;
                }
                else
                {
                    PopUp.PopUpOK.ShowDialog("Can not get Gun Size for Non-PERF Type", this._Name);
                    return SummitLib.Enums.GunSize.NA;
                }
            }

            public ServiceRun(string name, string deepestdepth, double maxtemp, string status, string engineer, DateTime starttime, DateTime stoptime,
                DateTime date, uint runno, EnumsStructs.ServiceType service, string description, double from, double to, double quantity,
                string unit, double unitprice, double amount)
                : this()
            {
                _Name = name;
                _DeepestDepth = deepestdepth;
                _MaxTemp = maxtemp;
                _Status = status;
                _Engineer = engineer;
                _StartTime = starttime;
                _StopTime = stoptime;

                _Date = date;
                _RunNo = runno;
                _ServiceName = service;
                _Description = description;
                _PerfLogFrom = from;
                _PerfLogTo = to;
                _Quantity = quantity;
                _Unit = unit;
                _UnitPrice = unitprice;
                _Amount = amount;

                Type = _ServiceName.Type;

                switch (this.Type)
                {
                    case KnownServiceType.PERF:
                        //=============================================================================================================//
                        //RunStatus
                        if (this._Status.Trim() == String.Empty)
                        {
                            PopUp.PopUpOK.ShowDialog("Status for this Run in Farpac is BLANK, Will put FIRED OK!", string.Format("Run {0} : {1}", _RunNo, _Name));
                            this.Status = RunStatus.FIRED_OK;
                        }
                        else if (this._Status.ToLower().Contains("ok")) this.Status = RunStatus.FIRED_OK;
                        else if (this._Status.ToLower().Contains("mis")) this.Status = RunStatus.MISFIRED;
                        else if (this._Status.ToLower().Contains("fail")) this.Status = RunStatus.MISRUN;
                        else this.Status = RunStatus.NA;
                        //=============================================================================================================//
                        //TopMD & BottomMD
                        try
                        {
                            double[] md = toMD(_DeepestDepth);
                            if (md.Length == 1)
                            {   // Only 1 Depth. Check if EQ or not
                                if (_Name.ToLower().Contains("eq")) { TopMD = md[0]; BottomMD = TopMD + 1.0; } // Assume EQ 1.0m 4Shots. Need implement more
                                else
                                {
                                    PopUp.PopUpOK.ShowDialog(string.Format("You miss Bottom Depth for this Perf Run : \"{0}\"\r\nWill put same Depth for Bottom", _Name), "Parse PERF Deepest Depth not CORRECT");
                                    TopMD = BottomMD = md[0];
                                }
                            }
                            else
                            {   // Length >= 2, never 0 because if 0 will throw Ex internal already
                                TopMD = md[0]; BottomMD = md[1];
                            }
                        }
                        catch (Exception ex)
                        {
                            PopUp.PopUpOK.ShowDialog(string.Format("Check this Perf. Run 's Deepest Depth again : \"{0}\" \r\n{1}", _DeepestDepth, ex.Message), string.Format("Run {0} : {1}", _RunNo, _Name));
                            TopMD = BottomMD = 0;
                        }
                        //=============================================================================================================//
                        break;

                    default:
                        //=============================================================================================================//
                        //RunStatus
                        if (this._Status.Trim() == String.Empty)
                        {
                            PopUp.PopUpOK.ShowDialog("Status for this Run in Farpac is BLANK, Will put RUN OK!", string.Format("Run {0} : {1}", _RunNo, _Name));
                            this.Status = RunStatus.RUN_OK;
                        }
                        else if (this._Status.ToLower().Contains("ok")) this.Status = RunStatus.RUN_OK;
                        else if (this._Status.ToLower().Contains("mis")) this.Status = RunStatus.MISRUN;
                        else if (this._Status.ToLower().Contains("fail")) this.Status = RunStatus.MISRUN;
                        else this.Status = RunStatus.NA;
                        //=============================================================================================================//
                        //TopMD & BottomMD
                        try
                        {
                            double[] md = toMD(_DeepestDepth);
                            if (md.Length == 1)
                            {   // Only 1 Depth. Add from 0 to that Depth
                                TopMD = 0; BottomMD = md[0];
                            }
                            else
                            {   // Length >= 2, never 0 because if 0 will throw Ex internal already
                                TopMD = md[0]; BottomMD = md[1];
                            }
                        }
                        catch (Exception ex)
                        {
                            PopUp.PopUpOK.ShowDialog(string.Format("Check this Service Run 's Deepest Depth again : \"{0}\" \r\n{1}", _DeepestDepth, ex.Message), string.Format("Run {0} : {1}", _RunNo, _Name));
                            TopMD = BottomMD = 0;
                        }
                        //=============================================================================================================//
                        break;
                }


            }

            public ServiceRun(string name, string deepestdepth, double maxtemp, string status, string engineer, uint runno)
                : this(name, deepestdepth, maxtemp, status, engineer, DateTime.Now, DateTime.Now,
                DateTime.Today, runno, new EnumsStructs.ServiceType(name), "N/A", 0, 0, 0, "", 0, 0)
            {

            }
        }
        #endregion

        #region JobBOM
        public enum JobBOM { NA, PERF, PLT, CBL, TMDL, PIPE_RECOVER, BRIDGE_PLUG, PRESSURE_TEMP, SURFACE_TEMP };
        public static class eJobBOM
        {
            private static string[] _arr = { "N/A", "PERFORATING - OTHERS BOM #7548", "PRODUCTION LOGGING BOM #14135", 
                                               "CEMENT & CASING EVAL BOM #7549", "PSL-LG-CH EVAL/RESERVOIR MONITORING-BOM #21614", 
                                               "PSL- LOG CASED HOLE PIPE RECOVERY #15412", "PSL-SSD-CASED HOLE BRIDGE PLUGSETING-BOM #14163", 
                                               "EXTENDED PRESSURE/TEMP SURVEY BOM #230994", "SURFACE RECORDING TEMP SURVEY BOM #231081" };
            private static string[] _arr2 = { "N/A", "PERF", "PLT", "CBL", "TMDL", "PIPE RECOVER", "BRIDGE PLUG", "PRESSURE/TEMP.", "SURFACE TEMP." };
            public static string ToData(JobBOM enumer)
            {
                return _arr[(int)enumer];
            }

            public static JobBOM ToEnum(string data)
            {
                int tmp = Array.IndexOf<string>(_arr, data);
                if (tmp == -1) return JobBOM.NA;
                return (JobBOM)tmp;
            }
        }
        #endregion

        public enum RunStatus { NA, FIRED_OK, RUN_OK, HUD_OK, MISFIRED, MISRUN, NO_COUNT };

        #region ServiceType
        public enum KnownServiceType { NA, PERF, GAUGE_CUTTER, JUNK_BASKET, FLUID_FINDER, TEMP_SUB, DUMMY_PATCH, TUBING_PATCH, CBL, TMDL };
        public struct ServiceType
        {
            private static string[] _arr = { "N/A", "PERFORATION", "GAUGE CUTTER", "JUNK BASKET", "FLUID FINDER", "TEMP SUB", "DUMMY PATCH", "TUBING PATCH", "CBL", "TMDL" };
            public static string ToData(KnownServiceType enumer)
            {
                return _arr[(int)enumer];
            }

            //private string _pattern; //pattern de biet Parse cai thang quy nao // Co nen gom het cac pattern vao mot List khong nhi ?
            private string _name;
            private KnownServiceType _type;
            public KnownServiceType Type
            {
                get { return _type; }
            }

            internal ServiceType(string parsename, KnownServiceType type)//, string pattern = "")
            {
                //if (pattern == "") { Regex.IsMatch(parsename, pattern); return; }
                // Else Regex Other
                _name = parsename;
                _type = type;
            }

            public ServiceType(string parsename) : this(parsename, toType(parsename)) { }

            private static KnownServiceType toType(string parsename)
            {
                if (IsPERF(parsename)) return KnownServiceType.PERF;
                else if (IsDUMMYPATCH(parsename)) return KnownServiceType.DUMMY_PATCH;
                else if (IsTUBINGPATCH(parsename)) return KnownServiceType.TUBING_PATCH;
                else if (IsGAUGECUTTER(parsename)) return KnownServiceType.GAUGE_CUTTER;
                else if (IsJUNKBASKET(parsename)) return KnownServiceType.JUNK_BASKET;
                else if (IsCBL(parsename)) return KnownServiceType.CBL;
                else if (IsTMDL(parsename)) return KnownServiceType.TMDL;
                // con TempSub & FluidFinder
                else return KnownServiceType.NA;
            }

            public static bool IsPERF(string parseName)
            {
                if (parseName == null) throw new InvalidOperationException("parseName for IsPERF is NULL");
                if (parseName == "") throw new InvalidOperationException("parseName for IsPERF is EMPTY");
                //string _parse = parseName.Trim(); // Remove leading & trailing space
                //while (_parse.Contains("  ")) _parse = _parse.Replace("  ", " "); // Remove double space by single space only

                return Regex.IsMatch(parseName, "perf", RegexOptions.IgnoreCase);
            }

            public static bool IsPATCH(string parseName)
            {
                if (parseName == null) throw new InvalidOperationException("parseName for IsPATCH is NULL");
                if (parseName == "") throw new InvalidOperationException("parseName for IsPATCH is EMPTY");
                //string _parse = parseName.Trim(); // Remove leading & trailing space
                //while (_parse.Contains("  ")) _parse = _parse.Replace("  ", " "); // Remove double space by single space only

                return Regex.IsMatch(parseName, "patch", RegexOptions.IgnoreCase);
            }

            public static bool IsTUBINGPATCH(string parseName)
            {
                if (parseName == null) throw new InvalidOperationException("parseName for IsTubingPatch is NULL");
                if (parseName == "") throw new InvalidOperationException("parseName for IsTubingPatch is EMPTY");
                return (IsPATCH(parseName) & !IsDUMMYPATCH(parseName));
            }

            public static bool IsDUMMYPATCH(string parseName)
            {
                if (parseName == null) throw new InvalidOperationException("parseName for IsDummyPatch is NULL");
                if (parseName == "") throw new InvalidOperationException("parseName for IsDummyPatch is EMPTY");
                return Regex.IsMatch(parseName, @"(^|[^a-z])((d\.|dummy|dum).*patch|d[^a-z]*patch)", RegexOptions.IgnoreCase);
                // (^|[^a-z]) : d.patch or dummypatch or what ever need at less 1 SPACE before or new line.
                // (d\.|dummy|dum).*patch : d.patch hoac dummypatch hoac dum.patch whatever. ".*" whatever character between d,dum,dummy with patch
                // d[^a-z]*patch : d.patch tuc la giua d va patch co the space, ., tab hay bat cu gi ngoai tru ky tu (a-z)
            }

            public static bool IsGAUGECUTTER(string parseName)
            {
                if (parseName == null) throw new InvalidOperationException("parseName for IsGaugeCutter is NULL");
                if (parseName == "") throw new InvalidOperationException("parseName for IsGaugeCutter is EMPTY");
                if (Regex.IsMatch(parseName, @"drift|(^|[^a-z])d[^a-z]*r([^a-z]|$)", RegexOptions.IgnoreCase)) // drift hoac la d.r
                    return !(Regex.IsMatch(parseName, @"g\.*(r\.*(\s+|$)|ring)|gauge[^a-z]*(r\.*(\s+|$)|ring)", RegexOptions.IgnoreCase) |
                        Regex.IsMatch(parseName, @"j\.*(c\.*(\s+|$)|catcher)|junk[^a-z]*(c\.*(\s+|$)|catcher)", RegexOptions.IgnoreCase) |
                        Regex.IsMatch(parseName, @"j\.*(b\.*(\s+|$)|basket)|junk[^a-z]*(b\.*(\s+|$)|basket)", RegexOptions.IgnoreCase));
                // g\.*r\.*\(s+|$) : g theo sau bi nhieu . cung duoc, roi den r bi nhieu . luon nhung phai co space it nhat 1 xuat hien dang sau hoac la endline $
                // gauge[^a-z]*(r\.*\s+|ring) : gauge roi den khong ky tu a-z nao het (co the space) roi den r.(bi nhieu . cung duoc) hoac la ring

                else
                    return Regex.IsMatch(parseName, @"(^|[^a-z])g[^a-z]*c([^a-z]|$)|(g\.|gauge)[^a-z]*(c\.*(\s+|$)|cutter)", RegexOptions.IgnoreCase);
                //(^|[^a-z]) : bat dau line hoac la khoang trong hoac . mien khong phai ky tu a-z : de chac chan tu g bat dau cua 1 ky tu.
                //g[^a-z]*c([^a-z]|$) : g roi den khoang trong hoac . mien khong phai ky tu a-z, roi den c lien sau la ky tu khong phai a-z hoac la endline.
                // g[^a-z]*c([^a-z]|$) : "g." hoac "gauge"
                // [^a-z]* : space hay . gi gi cung duoc mien sao khong co ky tu xen giua.
                // c\.*\(s+|$) : c co the co . (bi nhieu cung duoc), nhung phai co ky tu space lien sau do hoac la ky tu endline
            }

            public static bool IsJUNKBASKET(string parseName)
            {
                if (parseName == null) throw new InvalidOperationException("parseName for IsJUNKBASKET is NULL");
                if (parseName == "") throw new InvalidOperationException("parseName for IsJUNKBASKETx is EMPTY");
                return Regex.IsMatch(parseName, @"g\.*(r\.*(\s+|$)|ring)|gauge[^a-z]*(r\.*(\s+|$)|ring)", RegexOptions.IgnoreCase) |
                        Regex.IsMatch(parseName, @"j\.*(c\.*(\s+|$)|catcher)|junk[^a-z]*(c\.*(\s+|$)|catcher)", RegexOptions.IgnoreCase) |
                        Regex.IsMatch(parseName, @"j\.*(b\.*(\s+|$)|basket)|junk[^a-z]*(b\.*(\s+|$)|basket)", RegexOptions.IgnoreCase);
                //(r\.*(\s+|$)|ring) : r. hoac ring, rieng r. thi co the la r co space hoac r het line. "\.*" : xuat hien bao nhieu . tuy thich
            }

            public static bool IsCBL(string parseName)
            {
                if (parseName == null) throw new InvalidOperationException("parseName for IsCBL is NULL");
                if (parseName == "") throw new InvalidOperationException("parseName for IsCBL is EMPTY");
                return Regex.IsMatch(parseName, @"cbl|(c\.|cement).*bond.*log", RegexOptions.IgnoreCase);
            }

            public static bool IsTMDL(string parseName)
            {
                if (parseName == null) throw new InvalidOperationException("parseName for IsCBL is NULL");
                if (parseName == "") throw new InvalidOperationException("parseName for IsCBL is EMPTY");
                return Regex.IsMatch(parseName, @"tmdl", RegexOptions.IgnoreCase);
            }

            public static bool operator ==(ServiceType serviceType1, ServiceType serviceType2)
            {
                return serviceType1.Equals(serviceType2);
            }

            public static bool operator !=(ServiceType serviceType1, ServiceType serviceType2)
            {
                return !serviceType1.Equals(serviceType2);
            }

            public override string ToString()
            {
                return _name + " & Type : " + _type.ToString();
            }

            public override int GetHashCode()
            {
                return ToString().GetHashCode();
            }

            public bool Equals(ServiceType serviceType)
            {
                return serviceType._type == _type;
            }

            public override bool Equals(object Object)
            {
                if (Object is ServiceType)
                    return Equals((ServiceType)Object);
                return false;
            }

            /*public static ServiceType Perforation
            {
                get { return new ServiceType("perf"); }
            }*/
        }
        #endregion
    }
}
